package com.oba.base.dao;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.model.DataModel;

import com.oba.base.interfaces.IBaseBo;
import com.oba.base.interfaces.IHsqlBuilder;
import com.oba.base.interfaces.IPager;
import com.oba.base.interfaces.PageCallBack;

/**
 * 数据库翻页器
 * 
 * @author han
 */
public class DBPager extends Pager implements IPager {
	private DataModel model;
	private PageCallBack pageCallBack;
	private int pageSize = 0;
	private int curPage;
	private int itemCount;
	private boolean isMultiCheck;
	private int pageCount;
	private Map<Long, Boolean> checkedMap = new HashMap<Long, Boolean>();
	private BaseDao dao;
	private boolean show = false;
	private IHsqlBuilder hqlbuider;

	/**
	 * @param pagerDataModel
	 *            翻页数据模型
	 * @param isMultiCheck
	 *            多选标识
	 */
	public DBPager(DBDataModel dbDataModel, boolean isMultiCheck, PageCallBack... pageCallBack) {
		this.isMultiCheck = isMultiCheck;
		this.model = dbDataModel;
		if (pageCallBack.length > 0)
			this.pageCallBack = pageCallBack[0];
		System.out.println("pageCallBack = ---------" + this.pageCallBack);
	}
	
	public void init() {
		hqlbuider.build();
		String hql = hqlbuider.getHsql();
		StringBuffer countSql = new StringBuffer();
		int fromIndex = hql.indexOf("from");
		int orderByIndex = hql.indexOf("order by");
		if (orderByIndex > 0)
			hql = hql.substring(0, orderByIndex);
		if (fromIndex == 0) {
			countSql.append("select count(*) ");
			countSql.append(hql);
		} else {
			String selitem = hql.substring(6, fromIndex).trim();
			countSql.append("select count(");
			countSql.append(selitem);
			countSql.append(") ");
			countSql.append(hql.substring(fromIndex));
		}
		List<Integer> countList = hqlbuider.getDao().find(countSql.toString(),
				hqlbuider.getValues());
		itemCount = countList.get(0).intValue();
		if (itemCount > pageSize) {
			show = true;
		} else {
			show = false;
		}
		pageCount = super.getPageCount();
		//curPage = -1;
		if (isMultiCheck)
			checkedMap.clear();
	}
	
	/**
	 * @param sql
	 *            根据传入sql查询数据
	 */
	public void find(IHsqlBuilder hql, BaseDao dao) {
		this.dao = dao;
		this.hqlbuider = hql;
		init();
		gotoPage(curPage);
	}

	/**
	 * 获取选中记录
	 * 
	 * @return 选中记录ID列表
	 */
	public List<Long> getCheckedIds() {
		saveCheckState();
		List<Long> checkedIds = new ArrayList<Long>();
		Iterator<Long> idIter = checkedMap.keySet().iterator();
		while (idIter.hasNext()) {
			checkedIds.add(idIter.next());
		}
		checkedMap.clear();
		restoreCheckState();
		return checkedIds;
	}

	/**
	 * 设置页面大小
	 */
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	/**
	 * 
	 * 判定是否需保存选取状态
	 */
	private boolean isNeedSaveCheckedIds() {
		return isMultiCheck && curPage != -1;
	}

	/**
	 * 保存选取状态
	 */
	private void saveCheckState() {
		if (isNeedSaveCheckedIds()) {
			List<? extends IBaseBo> curPageList = (List<? extends IBaseBo>) model.getWrappedData();
			for (IBaseBo bo : curPageList) {
				if (bo.isChecked()) {
					checkedMap.put(bo.getId(), Boolean.TRUE);
				} else {
					checkedMap.remove(bo.getId());
				}

			}
		}
	}

	/**
	 * 返回所有的数据
	 * 
	 * @return
	 */
	public List<IBaseBo> getAllData() {
		return dao.find(hqlbuider);
	}

	/**
	 * 恢复选取状态
	 */
	private void restoreCheckState() {
		if (isMultiCheck && model.getRowCount() > 0) {
			List<? extends IBaseBo> curPageList = (List<? extends IBaseBo>) model.getWrappedData();
			for (IBaseBo bo : curPageList) {
				Boolean checked = checkedMap.get(bo.getId());
				if (checked != null) {
					bo.setChecked(true);
				} else {
					bo.setChecked(false);
				}

			}
			// model.setWrappedData(curPageList);
		}
	}

	/**
	 * 加载指定页
	 */
	@Override
	protected void loadPage(int page) {
		saveCheckState();
		curPage = page;
		List list = null;
		list = dao.find(hqlbuider, (curPage - 1) * pageSize, pageSize);
		model.setWrappedData(list);
		if (pageCallBack != null)
			pageCallBack.afterLoadPage(list);
		restoreCheckState();
	}

	/**
	 * 获取当前页码
	 */
	public int getCurPage() {
		return curPage;
	}

	/**
	 * 获取记录总数
	 */
	public int getItemCount() {
		return itemCount;
	}

	/**
	 * 获取页面大小
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * 获取总页数
	 */
	@Override
	public int getPageCount() {
		return pageCount;
	}

	public boolean isShow() {
		return show;
	}
}
